"""
Main application module for the CLU API service.

本模块是CLU API服务的主要入口点，负责初始化FastAPI应用、配置中间件、
注册路由和执行启动健康检查。

主要功能：
- FastAPI应用初始化和配置
- CORS中间件配置
- 自定义异常处理器
- 启动时CosmosDB健康检查
- 路由注册和应用生命周期管理

最小实现调用方式：
    python main.py

作者: ZHWA
创建时间: 2025-09-15 20:27:26 CST
"""

import asyncio
from contextlib import asynccontextmanager
from typing import AsyncGenerator

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse

from config import settings
from routers import project_router, clu_router, utils_router, health_router, logs_router, utils_service
from exceptions import CLUServiceError
from log import setup_logger, LoggingMiddleware, app_logger

setup_logger()

async def perform_startup_health_check() -> None:
    """
    执行启动健康检查。
    
    检查CosmosDB连接和关键配置，根据配置决定是否允许应用继续启动。
    支持严格模式（检查失败则终止启动）和宽松模式（检查失败但记录警告）。
    
    Raises:
        Exception: 当严格模式下健康检查失败时
    """
    if not settings.startup_health_check_enabled:
        app_logger.info("启动健康检查已禁用，跳过检查")
        return
    
    app_logger.info("开始执行启动健康检查...")
    health_check_errors = []
    
    # CosmosDB连通性检查
    try:
        from models import CosmosDBQueryRequest, CheckedApplicationsRequest
        
        app_logger.info("正在检查CosmosDB连接...")
        
        try:
            test_request = CosmosDBQueryRequest(target_key="System.LUIS.ThresholdScore")
            await asyncio.wait_for(
                utils_service.query_cosmos_setting(test_request),
                timeout=settings.startup_health_check_timeout
            )
            app_logger.info("CosmosDB连接检查通过")
            
            checked_apps_request = CheckedApplicationsRequest(checked=True)
            response = await asyncio.wait_for(
                utils_service.get_checked_applications(checked_apps_request),
                timeout=settings.startup_health_check_timeout
            )
            
            if not response.application_names:
                warning_msg = "⚠ CosmosDB中未找到已检查的应用程序配置，某些功能可能无法正常工作"
                app_logger.warning(warning_msg)
                if settings.cosmos_health_check_required:
                    health_check_errors.append("未找到已检查的应用程序配置")
            else:
                app_logger.info(f"找到{response.filtered_count}个已检查的应用程序")
            
            threshold_response = await utils_service.query_cosmos_setting(test_request)
            if threshold_response.found:
                app_logger.info("置信度阈值配置检查通过")
            else:
                app_logger.warning("⚠ 未找到置信度阈值配置，将使用默认行为")
                
        except asyncio.TimeoutError:
            error_msg = f"CosmosDB健康检查超时（{settings.startup_health_check_timeout}秒）"
            app_logger.error(f"✗ {error_msg}")
            health_check_errors.append(error_msg)
        except Exception as e:
            error_msg = f"CosmosDB健康检查失败: {str(e)}"
            app_logger.error(f"✗ {error_msg}")
            health_check_errors.append(error_msg)
            
    except ImportError as e:
        error_msg = f"导入依赖模块失败: {str(e)}"
        app_logger.error(f"✗ {error_msg}")
    except Exception as e:
        error_msg = f"健康检查过程中发生未预期的错误: {str(e)}"
        app_logger.error(f"✗ {error_msg}")
        health_check_errors.append(error_msg)
    
    if health_check_errors:
        if settings.cosmos_health_check_required:
            error_summary = "; ".join(health_check_errors)
            app_logger.critical(f"启动健康检查失败（严格模式），应用将终止启动: {error_summary}")
            raise RuntimeError(f"启动健康检查失败: {error_summary}")
        else:
            warning_summary = "; ".join(health_check_errors)
            app_logger.warning(f"启动健康检查发现问题（宽松模式），应用将继续启动: {warning_summary}")
    else:
        app_logger.success("启动健康检查全部通过")


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    """
    应用生命周期管理器。
    
    处理应用启动和关闭时的资源管理和健康检查。
    """
    settings.display_config_info()
    
    # 启动时执行健康检查
    try:
        await perform_startup_health_check()
        app_logger.success("CLU API Service 启动完成")
    except Exception as e:
        app_logger.critical(f"应用启动失败: {str(e)}")
        raise
    
    yield
    
    app_logger.info("CLU API Service 正在关闭...")
    await utils_service.close()


app = FastAPI(
    title="CLU API Service",
    description="Conversational Language Understanding API Service",
    version="1.0.0",
    lifespan=lifespan
)

# 添加日志中间件（必须在CORS中间件之前）
app.add_middleware(LoggingMiddleware)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.exception_handler(CLUServiceError)
async def clu_service_exception_handler(request: Request, exc: CLUServiceError):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.message},
    )

app.include_router(project_router)
app.include_router(clu_router)
app.include_router(utils_router)
app.include_router(health_router)
app.include_router(logs_router)

if __name__ == "__main__":
    import uvicorn
    
    app_logger.info(f"正在启动 CLU API Service，监听地址: {settings.host}:{settings.port}")
    
    uvicorn.run(
        "main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.reload,
        access_log=False
    )
